package twoD.IsoPfem.EmbeddedCrackModel;

import inf.jlinalg.ArrayVector;
import inf.jlinalg.IVector;
import oneD.fem.algorithm.MyLinalg;

public class LoadingFunction {

	private double Dnn_;
	private double Dss_;
	private ITractionSeparationLaw TSlaw_;

	public LoadingFunction(ITractionSeparationLaw g, double Dnn, double Dss,
			double ft, double ef) {
		Dnn_ = Dnn;
		Dss_ = Dss;
		TSlaw_ = g;
	}

	public double getDnn() {
		return Dnn_;
	}

	public double getDss() {
		return Dss_;
	}

	public ITractionSeparationLaw getTractionSeparationLaw() {
		return TSlaw_;
	}

	/**
	 * 
	 * @param etilde
	 * @param gamma
	 * @return true if the parameters satisfy loading function
	 */
	public boolean check(double etilde, double gamma) {
		return (F(etilde) - gamma) < 0;
	}

	/**
	 * 
	 * @param etilde
	 * @return value of first term in loading function
	 */
	public double F(double etilde) {
		return Dnn_ * etilde / TSlaw_.g(etilde);
	}

	/**
	 * 
	 * @param en
	 * @return derivative of F w.r.t etilde
	 */
	public double dFde(double en) {
		final double g = TSlaw_.g(en);
		return Dnn_ / g - Dnn_ * en * TSlaw_.dg(en) / Math.pow(g, 2);
	}

	/**
	 * 
	 * @param e
	 *            crack opening parameters
	 * @return value of first term in loading function
	 */
	public double F(IVector e) {
		double en = e.get(0);
		double es = e.get(1);
		double etilde = Math.sqrt(en * en + Dss_ / Dnn_ * es * es);
		// System.out.println("en=" + en + " ,es=" + es + " ,etilde=" + etilde);
		return F(etilde);
	}

	/**
	 * 
	 * @param e
	 *            crack opening parameters
	 * @return derivative of F w.r.t e
	 */
	public IVector dFde(IVector e) {
		IVector f = new ArrayVector(2, 1);
		double en = e.get(0);
		double es = e.get(1);
		double etilde = Math.sqrt(en * en + Dss_ / Dnn_ * es * es);

		f.set(0, en / etilde);
		f.set(1, Dss_ / Dnn_ * es / etilde);

		double tmp = dFde(etilde);
		MyLinalg.scale(tmp, f);

		return f;
	}

	/**
	 * 
	 * @param e
	 *            crack opening parameters
	 * @return derivative of F*=1/F w.r.t e
	 */
	public IVector dFstarde(IVector e) {
		IVector f = dFde(e);
		double tmp = F(e);
		MyLinalg.scale(-1.0 / (tmp * tmp), f);

		return f;
	}
}
